home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / r_edgea.s < prev    next >
Text File  |  2000-05-22  |  18KB  |  751 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. //
  21. // r_edgea.s
  22. // x86 assembly-language edge-processing code.
  23. //
  24.  
  25. #include "asm_i386.h"
  26. #include "quakeasm.h"
  27. #include "asm_draw.h"
  28.  
  29. #if    id386
  30.  
  31.     .data
  32. Ltemp:                    .long    0
  33. float_1_div_0100000h:    .long    0x35800000    // 1.0/(float)0x100000
  34. float_point_999:        .single    0.999
  35. float_1_point_001:        .single    1.001
  36.  
  37.     .text
  38.  
  39. //--------------------------------------------------------------------
  40.  
  41. #define edgestoadd    4+8        // note odd stack offsets because of interleaving
  42. #define edgelist    8+12    // with pushes
  43.  
  44. .globl C(R_EdgeCodeStart)
  45. C(R_EdgeCodeStart):
  46.  
  47. .globl C(R_InsertNewEdges)
  48. C(R_InsertNewEdges):
  49.     pushl    %edi
  50.     pushl    %esi                // preserve register variables
  51.     movl    edgestoadd(%esp),%edx
  52.     pushl    %ebx
  53.     movl    edgelist(%esp),%ecx
  54.  
  55. LDoNextEdge:
  56.     movl    et_u(%edx),%eax
  57.     movl    %edx,%edi
  58.  
  59. LContinueSearch:
  60.     movl    et_u(%ecx),%ebx
  61.     movl    et_next(%ecx),%esi
  62.     cmpl    %ebx,%eax
  63.     jle        LAddedge
  64.     movl    et_u(%esi),%ebx
  65.     movl    et_next(%esi),%ecx
  66.     cmpl    %ebx,%eax
  67.     jle        LAddedge2
  68.     movl    et_u(%ecx),%ebx
  69.     movl    et_next(%ecx),%esi
  70.     cmpl    %ebx,%eax
  71.     jle        LAddedge
  72.     movl    et_u(%esi),%ebx
  73.     movl    et_next(%esi),%ecx
  74.     cmpl    %ebx,%eax
  75.     jg        LContinueSearch
  76.  
  77. LAddedge2:
  78.     movl    et_next(%edx),%edx
  79.     movl    et_prev(%esi),%ebx
  80.     movl    %esi,et_next(%edi)
  81.     movl    %ebx,et_prev(%edi)
  82.     movl    %edi,et_next(%ebx)
  83.     movl    %edi,et_prev(%esi)
  84.     movl    %esi,%ecx
  85.  
  86.     cmpl    $0,%edx
  87.     jnz        LDoNextEdge
  88.     jmp        LDone
  89.  
  90.     .align 4
  91. LAddedge:
  92.     movl    et_next(%edx),%edx
  93.     movl    et_prev(%ecx),%ebx
  94.     movl    %ecx,et_next(%edi)
  95.     movl    %ebx,et_prev(%edi)
  96.     movl    %edi,et_next(%ebx)
  97.     movl    %edi,et_prev(%ecx)
  98.  
  99.     cmpl    $0,%edx
  100.     jnz        LDoNextEdge
  101.  
  102. LDone:
  103.     popl    %ebx                // restore register variables
  104.     popl    %esi
  105.     popl    %edi
  106.  
  107.     ret
  108.  
  109. //--------------------------------------------------------------------
  110.  
  111. #define predge    4+4
  112.  
  113. .globl C(R_RemoveEdges)
  114. C(R_RemoveEdges):
  115.     pushl    %ebx
  116.     movl    predge(%esp),%eax
  117.  
  118. Lre_loop:
  119.     movl    et_next(%eax),%ecx
  120.     movl    et_nextremove(%eax),%ebx
  121.     movl    et_prev(%eax),%edx
  122.     testl    %ebx,%ebx
  123.     movl    %edx,et_prev(%ecx)
  124.     jz        Lre_done
  125.     movl    %ecx,et_next(%edx)
  126.  
  127.     movl    et_next(%ebx),%ecx
  128.     movl    et_prev(%ebx),%edx
  129.     movl    et_nextremove(%ebx),%eax
  130.     movl    %edx,et_prev(%ecx)
  131.     testl    %eax,%eax
  132.     movl    %ecx,et_next(%edx)
  133.     jnz        Lre_loop
  134.  
  135.     popl    %ebx
  136.     ret
  137.  
  138. Lre_done:
  139.     movl    %ecx,et_next(%edx)
  140.     popl    %ebx
  141.  
  142.     ret
  143.  
  144. //--------------------------------------------------------------------
  145.  
  146. #define pedgelist    4+4        // note odd stack offset because of interleaving
  147.                             // with pushes
  148.  
  149. .globl C(R_StepActiveU)
  150. C(R_StepActiveU):
  151.     pushl    %edi
  152.     movl    pedgelist(%esp),%edx
  153.     pushl    %esi                // preserve register variables
  154.     pushl    %ebx
  155.  
  156.     movl    et_prev(%edx),%esi
  157.  
  158. LNewEdge:
  159.     movl    et_u(%esi),%edi
  160.  
  161. LNextEdge:
  162.     movl    et_u(%edx),%eax
  163.     movl    et_u_step(%edx),%ebx
  164.     addl    %ebx,%eax
  165.     movl    et_next(%edx),%esi
  166.     movl    %eax,et_u(%edx)
  167.     cmpl    %edi,%eax
  168.     jl        LPushBack
  169.  
  170.     movl    et_u(%esi),%edi
  171.     movl    et_u_step(%esi),%ebx
  172.     addl    %ebx,%edi
  173.     movl    et_next(%esi),%edx
  174.     movl    %edi,et_u(%esi)
  175.     cmpl    %eax,%edi
  176.     jl        LPushBack2
  177.  
  178.     movl    et_u(%edx),%eax
  179.     movl    et_u_step(%edx),%ebx
  180.     addl    %ebx,%eax
  181.     movl    et_next(%edx),%esi
  182.     movl    %eax,et_u(%edx)
  183.     cmpl    %edi,%eax
  184.     jl        LPushBack
  185.  
  186.     movl    et_u(%esi),%edi
  187.     movl    et_u_step(%esi),%ebx
  188.     addl    %ebx,%edi
  189.     movl    et_next(%esi),%edx
  190.     movl    %edi,et_u(%esi)
  191.     cmpl    %eax,%edi
  192.     jnl        LNextEdge
  193.  
  194. LPushBack2:
  195.     movl    %edx,%ebx
  196.     movl    %edi,%eax
  197.     movl    %esi,%edx
  198.     movl    %ebx,%esi
  199.  
  200. LPushBack:
  201. // push it back to keep it sorted
  202.     movl    et_prev(%edx),%ecx
  203.     movl    et_next(%edx),%ebx
  204.  
  205. // done if the -1 in edge_aftertail triggered this
  206.     cmpl    $(C(edge_aftertail)),%edx
  207.     jz        LUDone
  208.  
  209. // pull the edge out of the edge list
  210.     movl    et_prev(%ecx),%edi
  211.     movl    %ecx,et_prev(%esi)
  212.     movl    %ebx,et_next(%ecx)
  213.  
  214. // find out where the edge goes in the edge list
  215. LPushBackLoop:
  216.     movl    et_prev(%edi),%ecx
  217.     movl    et_u(%edi),%ebx
  218.     cmpl    %ebx,%eax
  219.     jnl        LPushBackFound
  220.  
  221.     movl    et_prev(%ecx),%edi
  222.     movl    et_u(%ecx),%ebx
  223.     cmpl    %ebx,%eax
  224.     jl        LPushBackLoop
  225.  
  226.     movl    %ecx,%edi
  227.  
  228. // put the edge back into the edge list
  229. LPushBackFound:
  230.     movl    et_next(%edi),%ebx
  231.     movl    %edi,et_prev(%edx)
  232.     movl    %ebx,et_next(%edx)
  233.     movl    %edx,et_next(%edi)
  234.     movl    %edx,et_prev(%ebx)
  235.  
  236.     movl    %esi,%edx
  237.     movl    et_prev(%esi),%esi
  238.  
  239.     cmpl    $(C(edge_tail)),%edx
  240.     jnz        LNewEdge
  241.  
  242. LUDone:
  243.     popl    %ebx                // restore register variables
  244.     popl    %esi
  245.     popl    %edi
  246.  
  247.     ret
  248.  
  249. //--------------------------------------------------------------------
  250.  
  251. #define surf    4        // note this is loaded before any pushes
  252.  
  253.     .align 4
  254. TrailingEdge:
  255.     movl    st_spanstate(%esi),%eax    // check for edge inversion
  256.     decl    %eax
  257.     jnz        LInverted
  258.  
  259.     movl    %eax,st_spanstate(%esi)
  260.     movl    st_insubmodel(%esi),%ecx
  261.     movl    0x12345678,%edx        // surfaces[1].st_next
  262. LPatch0:
  263.     movl    C(r_bmodelactive),%eax
  264.     subl    %ecx,%eax
  265.     cmpl    %esi,%edx
  266.     movl    %eax,C(r_bmodelactive)
  267.     jnz        LNoEmit                // surface isn't on top, just remove
  268.  
  269. // emit a span (current top going away)
  270.     movl    et_u(%ebx),%eax
  271.     shrl    $20,%eax                // iu = integral pixel u
  272.     movl    st_last_u(%esi),%edx
  273.     movl    st_next(%esi),%ecx
  274.     cmpl    %edx,%eax
  275.     jle        LNoEmit2                // iu <= surf->last_u, so nothing to emit
  276.  
  277.     movl    %eax,st_last_u(%ecx)    // surf->next->last_u = iu;
  278.     subl    %edx,%eax
  279.     movl    %edx,espan_t_u(%ebp)        // span->u = surf->last_u;
  280.  
  281.     movl    %eax,espan_t_count(%ebp)    // span->count = iu - span->u;
  282.     movl    C(current_iv),%eax
  283.     movl    %eax,espan_t_v(%ebp)        // span->v = current_iv;
  284.     movl    st_spans(%esi),%eax
  285.     movl    %eax,espan_t_pnext(%ebp)    // span->pnext = surf->spans;
  286.     movl    %ebp,st_spans(%esi)            // surf->spans = span;
  287.     addl    $(espan_t_size),%ebp
  288.  
  289.     movl    st_next(%esi),%edx        // remove the surface from the surface
  290.     movl    st_prev(%esi),%esi        // stack
  291.  
  292.     movl    %edx,st_next(%esi)
  293.     movl    %esi,st_prev(%edx)
  294.     ret
  295.  
  296. LNoEmit2:
  297.     movl    %eax,st_last_u(%ecx)    // surf->next->last_u = iu;
  298.     movl    st_next(%esi),%edx        // remove the surface from the surface
  299.     movl    st_prev(%esi),%esi        // stack
  300.  
  301.     movl    %edx,st_next(%esi)
  302.     movl    %esi,st_prev(%edx)
  303.     ret
  304.  
  305. LNoEmit:
  306.     movl    st_next(%esi),%edx        // remove the surface from the surface
  307.     movl    st_prev(%esi),%esi        // stack
  308.  
  309.     movl    %edx,st_next(%esi)
  310.     movl    %esi,st_prev(%edx)
  311.     ret
  312.  
  313. LInverted:
  314.     movl    %eax,st_spanstate(%esi)
  315.     ret
  316.  
  317. //--------------------------------------------------------------------
  318.  
  319. // trailing edge only
  320. Lgs_trailing:
  321.     pushl    $Lgs_nextedge
  322.     jmp        TrailingEdge
  323.  
  324.  
  325. .globl C(R_GenerateSpans)
  326. C(R_GenerateSpans):
  327.     pushl    %ebp                // preserve caller's stack frame
  328.     pushl    %edi
  329.     pushl    %esi                // preserve register variables
  330.     pushl    %ebx
  331.  
  332. // clear active surfaces to just the background surface
  333.     movl    C(surfaces),%eax
  334.     movl    C(edge_head_u_shift20),%edx
  335.     addl    $(st_size),%eax
  336. // %ebp = span_p throughout
  337.     movl    C(span_p),%ebp
  338.  
  339.     movl    $0,C(r_bmodelactive)
  340.  
  341.     movl    %eax,st_next(%eax)
  342.     movl    %eax,st_prev(%eax)
  343.     movl    %edx,st_last_u(%eax)
  344.     movl    C(edge_head)+et_next,%ebx        // edge=edge_head.next
  345.  
  346. // generate spans
  347.     cmpl    $(C(edge_tail)),%ebx        // done if empty list
  348.     jz        Lgs_lastspan
  349.  
  350. Lgs_edgeloop:
  351.  
  352.     movl    et_surfs(%ebx),%edi
  353.     movl    C(surfaces),%eax
  354.     movl    %edi,%esi
  355.     andl    $0xFFFF0000,%edi
  356.     andl    $0xFFFF,%esi
  357.     jz        Lgs_leading        // not a trailing edge
  358.  
  359. // it has a left surface, so a surface is going away for this span
  360.     shll    $(SURF_T_SHIFT),%esi
  361.     addl    %eax,%esi
  362.     testl    %edi,%edi
  363.     jz        Lgs_trailing
  364.  
  365. // both leading and trailing
  366.     call    TrailingEdge
  367.     movl    C(surfaces),%eax
  368.  
  369. // ---------------------------------------------------------------
  370. // handle a leading edge
  371. // ---------------------------------------------------------------
  372.  
  373. Lgs_leading:
  374.     shrl    $16-SURF_T_SHIFT,%edi
  375.     movl    C(surfaces),%eax
  376.     addl    %eax,%edi
  377.     movl    0x12345678,%esi        // surf2 = surfaces[1].next;
  378. LPatch2:
  379.     movl    st_spanstate(%edi),%edx
  380.     movl    st_insubmodel(%edi),%eax
  381.     testl    %eax,%eax
  382.     jnz        Lbmodel_leading
  383.  
  384. // handle a leading non-bmodel edge
  385.  
  386. // don't start a span if this is an inverted span, with the end edge preceding
  387. // the start edge (that is, we've already seen the end edge)
  388.     testl    %edx,%edx
  389.     jnz        Lxl_done
  390.  
  391.  
  392. // if (surf->key < surf2->key)
  393. //        goto newtop;
  394.     incl    %edx
  395.     movl    st_key(%edi),%eax
  396.     movl    %edx,st_spanstate(%edi)
  397.     movl    st_key(%esi),%ecx
  398.     cmpl    %ecx,%eax
  399.     jl        Lnewtop
  400.  
  401. // main sorting loop to search through surface stack until insertion point
  402. // found. Always terminates because background surface is sentinel
  403. // do
  404. // {
  405. //         surf2 = surf2->next;
  406. // } while (surf->key >= surf2->key);
  407. Lsortloopnb:
  408.     movl    st_next(%esi),%esi
  409.     movl    st_key(%esi),%ecx
  410.     cmpl    %ecx,%eax
  411.     jge        Lsortloopnb
  412.  
  413.     jmp        LInsertAndExit
  414.  
  415.  
  416. // handle a leading bmodel edge
  417.     .align    4
  418. Lbmodel_leading:
  419.  
  420. // don't start a span if this is an inverted span, with the end edge preceding
  421. // the start edge (that is, we've already seen the end edge)
  422.     testl    %edx,%edx
  423.     jnz        Lxl_done
  424.  
  425.     movl    C(r_bmodelactive),%ecx
  426.     incl    %edx
  427.     incl    %ecx
  428.     movl    %edx,st_spanstate(%edi)
  429.     movl    %ecx,C(r_bmodelactive)
  430.  
  431. // if (surf->key < surf2->key)
  432. //        goto newtop;
  433.     movl    st_key(%edi),%eax
  434.     movl    st_key(%esi),%ecx
  435.     cmpl    %ecx,%eax
  436.     jl        Lnewtop
  437.  
  438. // if ((surf->key == surf2->key) && surf->insubmodel)
  439. // {
  440.     jz        Lzcheck_for_newtop
  441.  
  442. // main sorting loop to search through surface stack until insertion point
  443. // found. Always terminates because background surface is sentinel
  444. // do
  445. // {
  446. //         surf2 = surf2->next;
  447. // } while (surf->key > surf2->key);
  448. Lsortloop:
  449.     movl    st_next(%esi),%esi
  450.     movl    st_key(%esi),%ecx
  451.     cmpl    %ecx,%eax
  452.     jg        Lsortloop
  453.  
  454.     jne        LInsertAndExit
  455.  
  456. // Do 1/z sorting to see if we've arrived in the right position
  457.     movl    et_u(%ebx),%eax
  458.     subl    $0xFFFFF,%eax
  459.     movl    %eax,Ltemp
  460.     fildl    Ltemp
  461.  
  462.     fmuls    float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) *
  463.                                 //      (1.0 / 0x100000);
  464.  
  465.     fld        %st(0)                // fu | fu
  466.     fmuls    st_d_zistepu(%edi)    // fu*surf->d_zistepu | fu
  467.     flds    C(fv)                    // fv | fu*surf->d_zistepu | fu
  468.     fmuls    st_d_zistepv(%edi)    // fv*surf->d_zistepv | fu*surf->d_zistepu | fu
  469.     fxch    %st(1)                // fu*surf->d_zistepu | fv*surf->d_zistepv | fu
  470.     fadds    st_d_ziorigin(%edi)    // fu*surf->d_zistepu + surf->d_ziorigin |
  471.                                 //  fv*surf->d_zistepv | fu
  472.  
  473.     flds    st_d_zistepu(%esi)    // surf2->d_zistepu |
  474.                                 //  fu*surf->d_zistepu + surf->d_ziorigin |
  475.                                 //  fv*surf->d_zistepv | fu
  476.     fmul    %st(3),%st(0)        // fu*surf2->d_zistepu |
  477.                                 //  fu*surf->d_zistepu + surf->d_ziorigin |
  478.                                 //  fv*surf->d_zistepv | fu
  479.     fxch    %st(1)                // fu*surf->d_zistepu + surf->d_ziorigin |
  480.                                 //  fu*surf2->d_zistepu |
  481.                                 //  fv*surf->d_zistepv | fu
  482.     faddp    %st(0),%st(2)        // fu*surf2->d_zistepu | newzi | fu
  483.  
  484.     flds    C(fv)                    // fv | fu*surf2->d_zistepu | newzi | fu
  485.     fmuls    st_d_zistepv(%esi)    // fv*surf2->d_zistepv |
  486.                                 //  fu*surf2->d_zistepu | newzi | fu
  487.     fld        %st(2)                // newzi | fv*surf2->d_zistepv |
  488.                                 //  fu*surf2->d_zistepu | newzi | fu
  489.     fmuls    float_point_999        // newzibottom | fv*surf2->d_zistepv |
  490.                                 //  fu*surf2->d_zistepu | newzi | fu
  491.  
  492.     fxch    %st(2)                // fu*surf2->d_zistepu | fv*surf2->d_zistepv |
  493.                                 //  newzibottom | newzi | fu
  494.     fadds    st_d_ziorigin(%esi)    // fu*surf2->d_zistepu + surf2->d_ziorigin |
  495.                                 //  fv*surf2->d_zistepv | newzibottom | newzi |
  496.                                 //  fu
  497.     faddp    %st(0),%st(1)        // testzi | newzibottom | newzi | fu
  498.     fxch    %st(1)                // newzibottom | testzi | newzi | fu
  499.  
  500. // if (newzibottom >= testzi)
  501. //     goto Lgotposition;
  502.  
  503.     fcomp    %st(1)                // testzi | newzi | fu
  504.  
  505.     fxch    %st(1)                // newzi | testzi | fu
  506.     fmuls    float_1_point_001    // newzitop | testzi | fu
  507.     fxch    %st(1)                // testzi | newzitop | fu
  508.  
  509.     fnstsw    %ax
  510.     testb    $0x01,%ah
  511.     jz        Lgotposition_fpop3
  512.  
  513. // if (newzitop >= testzi)
  514. // {
  515.  
  516.     fcomp    %st(1)                // newzitop | fu
  517.     fnstsw    %ax
  518.     testb    $0x45,%ah
  519.     jz        Lsortloop_fpop2
  520.  
  521. // if (surf->d_zistepu >= surf2->d_zistepu)
  522. //     goto newtop;
  523.  
  524.     flds    st_d_zistepu(%edi)    // surf->d_zistepu | newzitop| fu
  525.     fcomps    st_d_zistepu(%esi)    // newzitop | fu
  526.     fnstsw    %ax
  527.     testb    $0x01,%ah
  528.     jz        Lgotposition_fpop2
  529.  
  530.     fstp    %st(0)                // clear the FPstack
  531.     fstp    %st(0)
  532.     movl    st_key(%edi),%eax
  533.     jmp        Lsortloop
  534.  
  535.  
  536. Lgotposition_fpop3:
  537.     fstp    %st(0)
  538. Lgotposition_fpop2:
  539.     fstp    %st(0)
  540.     fstp    %st(0)
  541.     jmp        LInsertAndExit
  542.  
  543.  
  544. // emit a span (obscures current top)
  545.  
  546. Lnewtop_fpop3:
  547.     fstp    %st(0)
  548. Lnewtop_fpop2:
  549.     fstp    %st(0)
  550.     fstp    %st(0)
  551.     movl    st_key(%edi),%eax        // reload the sorting key
  552.  
  553. Lnewtop:
  554.     movl    et_u(%ebx),%eax
  555.     movl    st_last_u(%esi),%edx
  556.     shrl    $20,%eax                // iu = integral pixel u
  557.     movl    %eax,st_last_u(%edi)    // surf->last_u = iu;
  558.     cmpl    %edx,%eax
  559.     jle        LInsertAndExit            // iu <= surf->last_u, so nothing to emit
  560.  
  561.     subl    %edx,%eax
  562.     movl    %edx,espan_t_u(%ebp)        // span->u = surf->last_u;
  563.  
  564.     movl    %eax,espan_t_count(%ebp)    // span->count = iu - span->u;
  565.     movl    C(current_iv),%eax
  566.     movl    %eax,espan_t_v(%ebp)        // span->v = current_iv;
  567.     movl    st_spans(%esi),%eax
  568.     movl    %eax,espan_t_pnext(%ebp)    // span->pnext = surf->spans;
  569.     movl    %ebp,st_spans(%esi)            // surf->spans = span;
  570.     addl    $(espan_t_size),%ebp
  571.  
  572. LInsertAndExit:
  573. // insert before surf2
  574.     movl    %esi,st_next(%edi)        // surf->next = surf2;
  575.     movl    st_prev(%esi),%eax
  576.     movl    %eax,st_prev(%edi)        // surf->prev = surf2->prev;
  577.     movl    %edi,st_prev(%esi)        // surf2->prev = surf;
  578.     movl    %edi,st_next(%eax)        // surf2->prev->next = surf;
  579.  
  580. // ---------------------------------------------------------------
  581. // leading edge done
  582. // ---------------------------------------------------------------
  583.  
  584. // ---------------------------------------------------------------
  585. // see if there are any more edges
  586. // ---------------------------------------------------------------
  587.  
  588. Lgs_nextedge:
  589.     movl    et_next(%ebx),%ebx
  590.     cmpl    $(C(edge_tail)),%ebx
  591.     jnz        Lgs_edgeloop
  592.  
  593. // clean up at the right edge
  594. Lgs_lastspan:
  595.  
  596. // now that we've reached the right edge of the screen, we're done with any
  597. // unfinished surfaces, so emit a span for whatever's on top
  598.     movl    0x12345678,%esi        // surfaces[1].st_next
  599. LPatch3:
  600.     movl    C(edge_tail_u_shift20),%eax
  601.     xorl    %ecx,%ecx
  602.     movl    st_last_u(%esi),%edx
  603.     subl    %edx,%eax
  604.     jle        Lgs_resetspanstate
  605.  
  606.     movl    %edx,espan_t_u(%ebp)
  607.     movl    %eax,espan_t_count(%ebp)
  608.     movl    C(current_iv),%eax
  609.     movl    %eax,espan_t_v(%ebp)
  610.     movl    st_spans(%esi),%eax
  611.     movl    %eax,espan_t_pnext(%ebp)
  612.     movl    %ebp,st_spans(%esi)
  613.     addl    $(espan_t_size),%ebp
  614.  
  615. // reset spanstate for all surfaces in the surface stack
  616. Lgs_resetspanstate:
  617.     movl    %ecx,st_spanstate(%esi)
  618.     movl    st_next(%esi),%esi
  619.     cmpl    $0x12345678,%esi        // &surfaces[1]
  620. LPatch4:
  621.     jnz        Lgs_resetspanstate
  622.  
  623. // store the final span_p
  624.     movl    %ebp,C(span_p)
  625.  
  626.     popl    %ebx                // restore register variables
  627.     popl    %esi
  628.     popl    %edi
  629.     popl    %ebp                // restore the caller's stack frame
  630.     ret
  631.  
  632.  
  633. // ---------------------------------------------------------------
  634. // 1/z sorting for bmodels in the same leaf
  635. // ---------------------------------------------------------------
  636.     .align    4
  637. Lxl_done:
  638.     incl    %edx
  639.     movl    %edx,st_spanstate(%edi)
  640.  
  641.     jmp        Lgs_nextedge
  642.  
  643.  
  644.     .align    4
  645. Lzcheck_for_newtop:
  646.     movl    et_u(%ebx),%eax
  647.     subl    $0xFFFFF,%eax
  648.     movl    %eax,Ltemp
  649.     fildl    Ltemp
  650.  
  651.     fmuls    float_1_div_0100000h // fu = (float)(edge->u - 0xFFFFF) *
  652.                                 //      (1.0 / 0x100000);
  653.  
  654.     fld        %st(0)                // fu | fu
  655.     fmuls    st_d_zistepu(%edi)    // fu*surf->d_zistepu | fu
  656.     flds    C(fv)                // fv | fu*surf->d_zistepu | fu
  657.     fmuls    st_d_zistepv(%edi)    // fv*surf->d_zistepv | fu*surf->d_zistepu | fu
  658.     fxch    %st(1)                // fu*surf->d_zistepu | fv*surf->d_zistepv | fu
  659.     fadds    st_d_ziorigin(%edi)    // fu*surf->d_zistepu + surf->d_ziorigin |
  660.                                 //  fv*surf->d_zistepv | fu
  661.  
  662.     flds    st_d_zistepu(%esi)    // surf2->d_zistepu |
  663.                                 //  fu*surf->d_zistepu + surf->d_ziorigin |
  664.                                 //  fv*surf->d_zistepv | fu
  665.     fmul    %st(3),%st(0)        // fu*surf2->d_zistepu |
  666.                                 //  fu*surf->d_zistepu + surf->d_ziorigin |
  667.                                 //  fv*surf->d_zistepv | fu
  668.     fxch    %st(1)                // fu*surf->d_zistepu + surf->d_ziorigin |
  669.                                 //  fu*surf2->d_zistepu |
  670.                                 //  fv*surf->d_zistepv | fu
  671.     faddp    %st(0),%st(2)        // fu*surf2->d_zistepu | newzi | fu
  672.  
  673.     flds    C(fv)                // fv | fu*surf2->d_zistepu | newzi | fu
  674.     fmuls    st_d_zistepv(%esi)    // fv*surf2->d_zistepv |
  675.                                 //  fu*surf2->d_zistepu | newzi | fu
  676.     fld        %st(2)                // newzi | fv*surf2->d_zistepv |
  677.                                 //  fu*surf2->d_zistepu | newzi | fu
  678.     fmuls    float_point_999        // newzibottom | fv*surf2->d_zistepv |
  679.                                 //  fu*surf2->d_zistepu | newzi | fu
  680.  
  681.     fxch    %st(2)                // fu*surf2->d_zistepu | fv*surf2->d_zistepv |
  682.                                 //  newzibottom | newzi | fu
  683.     fadds    st_d_ziorigin(%esi)    // fu*surf2->d_zistepu + surf2->d_ziorigin |
  684.                                 //  fv*surf2->d_zistepv | newzibottom | newzi |
  685.                                 //  fu
  686.     faddp    %st(0),%st(1)        // testzi | newzibottom | newzi | fu
  687.     fxch    %st(1)                // newzibottom | testzi | newzi | fu
  688.  
  689. // if (newzibottom >= testzi)
  690. //     goto newtop;
  691.  
  692.     fcomp    %st(1)                // testzi | newzi | fu
  693.  
  694.     fxch    %st(1)                // newzi | testzi | fu
  695.     fmuls    float_1_point_001    // newzitop | testzi | fu
  696.     fxch    %st(1)                // testzi | newzitop | fu
  697.  
  698.     fnstsw    %ax
  699.     testb    $0x01,%ah
  700.     jz        Lnewtop_fpop3
  701.  
  702. // if (newzitop >= testzi)
  703. // {
  704.  
  705.     fcomp    %st(1)                // newzitop | fu
  706.     fnstsw    %ax
  707.     testb    $0x45,%ah
  708.     jz        Lsortloop_fpop2
  709.  
  710. // if (surf->d_zistepu >= surf2->d_zistepu)
  711. //     goto newtop;
  712.  
  713.     flds    st_d_zistepu(%edi)    // surf->d_zistepu | newzitop | fu
  714.     fcomps    st_d_zistepu(%esi)    // newzitop | fu
  715.     fnstsw    %ax
  716.     testb    $0x01,%ah
  717.     jz        Lnewtop_fpop2
  718.  
  719. Lsortloop_fpop2:
  720.     fstp    %st(0)                // clear the FP stack
  721.     fstp    %st(0)
  722.     movl    st_key(%edi),%eax
  723.     jmp        Lsortloop
  724.  
  725.  
  726. .globl C(R_EdgeCodeEnd)
  727. C(R_EdgeCodeEnd):
  728.  
  729.  
  730. //----------------------------------------------------------------------
  731. // Surface array address code patching routine
  732. //----------------------------------------------------------------------
  733.  
  734.     .align 4
  735. .globl C(R_SurfacePatch)
  736. C(R_SurfacePatch):
  737.  
  738.     movl    C(surfaces),%eax
  739.     addl    $(st_size),%eax
  740.     movl    %eax,LPatch4-4
  741.  
  742.     addl    $(st_next),%eax
  743.     movl    %eax,LPatch0-4
  744.     movl    %eax,LPatch2-4
  745.     movl    %eax,LPatch3-4
  746.  
  747.     ret
  748.  
  749. #endif    // id386
  750.  
  751.